/**
 * Project Name:HuayuanPay
 * File Name:LocalHttpClient.java
 * Package Name:com.sxhuayuan.util
 * Date:2016年11月6日下午7:33:49
 * Copyright (c) 2016, sxhuayuan.com All Rights Reserved.
 *
 */

package com.sxhuayuan.parking.compenent.http;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LocalHttpClient {

	private static final Logger logger = LoggerFactory.getLogger(LocalHttpClient.class);

	private static int timeout = 5000;

	private static int retryExecutionCount = 2;

	/**
	 * 此处解释下MaxtTotal和DefaultMaxPerRoute的区别： 1、MaxtTotal是整个池子的大小；
	 * 2、DefaultMaxPerRoute是根据连接到的主机对MaxTotal的一个细分；比如： MaxtTotal=400
	 * DefaultMaxPerRoute=200 而我只连接到http://sishuok.com时，到这个主机的并发最多只有200；而不是400；
	 * 而我连接到http://sishuok.com 和
	 * http://qq.com时，到每个主机的并发最多只有200；即加起来是400（但不能超过400
	 * ）；所以起作用的设置是DefaultMaxPerRoute。
	 */
	protected static CloseableHttpClient httpClient = HttpClientFactory.createHttpClient(100, 10, timeout,
			retryExecutionCount);

	private static Map<String, CloseableHttpClient> httpClient_mchKeyStore = new HashMap<String, CloseableHttpClient>();

	/**
	 * @since 2.7.0
	 * @param timeout
	 *            timeout
	 */
	public static void setTimeout(int timeout) {
		LocalHttpClient.timeout = timeout;
	}

	/**
	 * @since 2.7.0
	 * @param retryExecutionCount
	 *            retryExecutionCount
	 */
	public static void setRetryExecutionCount(int retryExecutionCount) {
		LocalHttpClient.retryExecutionCount = retryExecutionCount;
	}

	/**
	 * 
	 * @param maxTotal
	 *            maxTotal
	 * @param maxPerRoute
	 *            maxPerRoute
	 */
	public static void init(int maxTotal, int maxPerRoute) {
		try {
			httpClient.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		httpClient = HttpClientFactory.createHttpClient(maxTotal, maxPerRoute, timeout, retryExecutionCount);
	}

	/**
	 * 初始化 MCH HttpClient KeyStore
	 * 
	 * @param mch_id
	 *            mch_id
	 * @param keyStoreFilePath
	 *            keyStoreFilePath
	 */
	public static void initMchKeyStore(String mch_id, String keyStoreFilePath) {
		try {
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			FileInputStream instream = new FileInputStream(new File(keyStoreFilePath));
			keyStore.load(instream, mch_id.toCharArray());
			instream.close();
			CloseableHttpClient httpClient = HttpClientFactory.createKeyMaterialHttpClient(keyStore, mch_id, timeout,
					retryExecutionCount);
			httpClient_mchKeyStore.put(mch_id, httpClient);
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (CertificateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static CloseableHttpResponse execute(HttpUriRequest request) {
		loggerRequest(request);
		try {
			return httpClient.execute(request, HttpClientContext.create());
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		return null;
	}

	/**
	 * 日志记录
	 * 
	 * @param request
	 *            request
	 * @return log request id
	 */
	private static String loggerRequest(HttpUriRequest request) {
		String id = UUID.randomUUID().toString();
		if (logger.isInfoEnabled() || logger.isDebugEnabled()) {
			if (request instanceof HttpEntityEnclosingRequestBase) {
				HttpEntityEnclosingRequestBase request_base = (HttpEntityEnclosingRequestBase) request;
				HttpEntity entity = request_base.getEntity();
				String content = null;
				// MULTIPART_FORM_DATA 请求类型判断
				if (entity.getContentType().toString().indexOf(ContentType.MULTIPART_FORM_DATA.getMimeType()) == -1) {
					try {
						content = EntityUtils.toString(entity);
					} catch (Exception e) {
						e.printStackTrace();
						logger.error(e.getMessage());
					}
				}
				logger.info("URI[{}] {} {} ContentLength:{} Content:{}", id, request.getURI().toString(),
						entity.getContentType(), entity.getContentLength(),
						content == null ? "multipart_form_data" : content);
			} else {
				logger.info("URI[{}] {}", id, request.getURI().toString());
			}
		}
		return id;
	}
}
